Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "fs,win: fix bug in paths with trailing slashes" #55527

Merged
merged 1 commit into from
Nov 2, 2024

Conversation

rvagg
Copy link
Member

@rvagg rvagg commented Oct 25, 2024

This reverts commit 00b2f07.

Reverts: #54160
Unfixes: #17801

Two problems with #54160 from my experience with things failing on v23:

  1. It assumes that you shouldn't be able to open(2) a directory and acts as if O_DIRECTORY has been supplied, which it hasn't. It's always been possible to fs.open() a directory and use the file descriptor for it. If I happen to pass a trailing slash it shouldn't matter.
  2. It throws, even if I supply a callback.

Example of code broken on v23 that's worked up until now:

const fs = require('fs')

fs.rmdir('_test', () => {
  fs.mkdir('_test', (err) => {
    if (err) return console.error(err)

    try {
      fs.open('_test/', 'r', (err, fd) => {
        if (err) return console.error(err)

        fs.fstat(fd, (err, stat) => {
          if (err) return console.error(err)

          console.log('isDirectory:', stat.isDirectory())
        })
      })
    } catch (err) {
      console.error('Why am I catching an error when I provided a callback?')
      console.error(err)
    }
  })
})

/cc @huseyinacacak-janea @mcollina @anonrig

@nodejs-github-bot nodejs-github-bot added fs Issues and PRs related to the fs subsystem / file system. needs-ci PRs that need a full CI run. labels Oct 25, 2024
rvagg added a commit to isaacs/st that referenced this pull request Oct 25, 2024
Copy link

codecov bot commented Oct 25, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 88.42%. Comparing base (53b1050) to head (98bfc2e).
Report is 57 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #55527      +/-   ##
==========================================
- Coverage   88.42%   88.42%   -0.01%     
==========================================
  Files         654      654              
  Lines      187552   187509      -43     
  Branches    36087    36075      -12     
==========================================
- Hits       165839   165800      -39     
+ Misses      14950    14947       -3     
+ Partials     6763     6762       -1     
Files with missing lines Coverage Δ
lib/fs.js 98.14% <100.00%> (+0.02%) ⬆️
lib/internal/fs/promises.js 98.24% <100.00%> (ø)
lib/internal/fs/streams.js 93.63% <100.00%> (ø)
lib/internal/fs/utils.js 99.69% <100.00%> (-0.02%) ⬇️

... and 26 files with indirect coverage changes

rvagg added a commit to isaacs/st that referenced this pull request Oct 25, 2024
rvagg added a commit to isaacs/st that referenced this pull request Oct 25, 2024
@huseyinacacak-janea
Copy link
Contributor

From what I've seen, the problem is in open and openSync. Instead of reverting the whole PR, we can just fix the issue in these functions by opening a new PR.
For example, below patch can fix this issue in open and openSync. There might be different fixes but I'm sharing this one to show my approach.

patch
diff --git a/lib/fs.js b/lib/fs.js
index e6ae9855a0d..6207bef8c05 100644
--- a/lib/fs.js
+++ b/lib/fs.js
@@ -537,7 +537,8 @@ function closeSync(fd) {
* @returns {void}
*/
function open(path, flags, mode, callback) {
-  path = getValidatedPath(path, 'path', { expectFile: true, syscall: 'open' });
+  const isDirectory = lstatSync(path, {throwIfNoEntry: false})?.isDirectory();
+  path = getValidatedPath(path, 'path', { expectFile: !isDirectory, syscall: 'open' });
 if (arguments.length < 3) {
   callback = flags;
   flags = 'r';
@@ -565,8 +566,9 @@ function open(path, flags, mode, callback) {
* @returns {number}
*/
function openSync(path, flags, mode) {
+  const isDirectory = lstatSync(path, {throwIfNoEntry: false})?.isDirectory();
 return binding.open(
-    getValidatedPath(path, 'path', { expectFile: true, syscall: 'open' }),
+    getValidatedPath(path, 'path', { expectFile: !isDirectory, syscall: 'open' }),
   stringToFlags(flags),
   parseFileMode(mode, 'mode', 0o666),
 );
diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js
index f5a9a3a8542..f029d28d752 100644
--- a/lib/internal/fs/promises.js
+++ b/lib/internal/fs/promises.js
@@ -633,7 +633,8 @@ async function copyFile(src, dest, mode) {
// Note that unlike fs.open() which uses numeric file descriptors,
// fsPromises.open() uses the fs.FileHandle class.
async function open(path, flags, mode) {
-  path = getValidatedPath(path, 'path', { expectFile: true, syscall: 'open' });
+  const stats = await lstat(path);
+  path = getValidatedPath(path, 'path', { expectFile: !stats.isDirectory(), syscall: 'open' });
 const flagsNumber = stringToFlags(flags);
 mode = parseFileMode(mode, 'mode', 0o666);
 return new FileHandle(await PromisePrototypeThen(

What do you think?

@rvagg
Copy link
Member Author

rvagg commented Oct 25, 2024

I don't really like that you're doing a stat before I get to open the file descriptor, part of the reason one might deal directly with file descriptors is to be able to manage the lifecycle much more carefully. In the particular use-case where this error came up for me I'm doing precisely this - open fd, do a stat on it, deal with it in a particular way if it's a directory or not, but hold on to the fd for further operations later; a very fine-grained handling of the filesystem in a particularly i/o heavy situation. Your solution now wants to essentially load my file descriptor twice before I can get my hands on it.

I'd also like errors to be dealt with via the callback if one is present, passing that down into getValidatedPath would seem appropriate so it can figure out whether to throw or return.

@blexrob
Copy link

blexrob commented Oct 30, 2024

This will probably also fix emscripten-core/emscripten#22812

@RafaelGSS
Copy link
Member

@rvagg However, landing this would result in another semver-major change I suppose.

@ruyadorno
Copy link
Member

@rvagg However, landing this would result in another semver-major change I suppose.

well, assuming this was an unintentional API change, it should be just a patch bugfix

@rvagg
Copy link
Member Author

rvagg commented Oct 30, 2024

I think it would have to be treated as a regression and therefore a semver-patch. It's unfortunate because the original fix was trying to address a problem and this undoes that. But maybe there's an alternative path to addressing that problem that doesn't introduce a regression could be bundled along with a revert of the initial attempt.

@rvagg
Copy link
Member Author

rvagg commented Oct 30, 2024

I note esbuild has also identified this as a problem.

@juanarbol
Copy link
Member

juanarbol commented Oct 31, 2024

I note esbuild has also identified this as a problem.

Same for webpack webpack/webpack#18891

This will fix #55609

Copy link
Member

@juanarbol juanarbol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@richardlau richardlau added the request-ci Add this label to start a Jenkins CI on a PR. label Oct 31, 2024
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Oct 31, 2024
@nodejs-github-bot
Copy link
Collaborator

@avivkeller avivkeller added the revert PRs that revert previously landed PRs. label Oct 31, 2024
@nodejs-github-bot
Copy link
Collaborator

@rvagg
Copy link
Member Author

rvagg commented Nov 1, 2024

Is the TLS test failure a known flaky?

---
duration_ms: 688.045
exitcode: 1
severity: fail
stack: |-
  node:events:485
        throw er; // Unhandled 'error' event
        ^

  Error: E4080000:error:0A00041A:SSL routines:ssl3_read_bytes:tlsv1 alert decode error:C:\workspace\node-compile-windows\node\deps\openssl\openssl\ssl\record\rec_layer_s3.c:1605:SSL alert number 50

  Emitted 'error' event on TLSSocket instance at:
      at TLSSocket._emitTLSError (node:_tls_wrap:1034:10)
      at TLSWrap.onerror (node:_tls_wrap:475:11) {
    library: 'SSL routines',
    reason: 'tlsv1 alert decode error',
    code: 'ERR_SSL_TLSV1_ALERT_DECODE_ERROR'
  }

  Node.js v24.0.0-pre
...

@nodejs-github-bot
Copy link
Collaborator

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@mcollina mcollina added dont-land-on-v18.x PRs that should not land on the v18.x-staging branch and should not be released in v18.x. dont-land-on-v20.x PRs that should not land on the v20.x-staging branch and should not be released in v20.x. dont-land-on-v22.x PRs that should not land on the v22.x-staging branch and should not be released in v22.x. labels Nov 1, 2024
@marco-ippolito marco-ippolito added the commit-queue Add this label to land a pull request using GitHub Actions. label Nov 2, 2024
@nodejs-github-bot nodejs-github-bot removed the commit-queue Add this label to land a pull request using GitHub Actions. label Nov 2, 2024
@nodejs-github-bot nodejs-github-bot merged commit 7b01758 into nodejs:main Nov 2, 2024
84 checks passed
@nodejs-github-bot
Copy link
Collaborator

Landed in 7b01758

louwers pushed a commit to louwers/node that referenced this pull request Nov 2, 2024
This reverts commit 00b2f07.

PR-URL: nodejs#55527
Fixes: nodejs#17801
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Stefan Stojanovic <stefan.stojanovic@janeasystems.com>
aduh95 pushed a commit that referenced this pull request Nov 5, 2024
This reverts commit 00b2f07.

PR-URL: #55527
Fixes: #17801
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Stefan Stojanovic <stefan.stojanovic@janeasystems.com>
aduh95 pushed a commit that referenced this pull request Nov 6, 2024
This reverts commit 00b2f07.

PR-URL: #55527
Fixes: #17801
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Stefan Stojanovic <stefan.stojanovic@janeasystems.com>
tpoisseau pushed a commit to tpoisseau/node that referenced this pull request Nov 21, 2024
This reverts commit 00b2f07.

PR-URL: nodejs#55527
Fixes: nodejs#17801
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Stefan Stojanovic <stefan.stojanovic@janeasystems.com>
jeremybobbin added a commit to jeremybobbin/webpack that referenced this pull request Dec 5, 2024
…6417

Looks like a nodejs bug, introduced in v23.0.0 - commit hash 00b2f07f
It should be fixed in v23.2.0 - dd9b6833

bug: nodejs/node#54160
fix: nodejs/node#55527

I am able to replicate this on v23.1.0.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dont-land-on-v18.x PRs that should not land on the v18.x-staging branch and should not be released in v18.x. dont-land-on-v20.x PRs that should not land on the v20.x-staging branch and should not be released in v20.x. dont-land-on-v22.x PRs that should not land on the v22.x-staging branch and should not be released in v22.x. fs Issues and PRs related to the fs subsystem / file system. needs-ci PRs that need a full CI run. revert PRs that revert previously landed PRs.
Projects
None yet
Development

Successfully merging this pull request may close these issues.